﻿

namespace Test
 module Switch = 

    open System
    open System.Windows
    open System.Windows.Media
    open System.Windows.Shapes
    open System.Windows.Controls
    open FsSignals.Signal
      
    module Switch1 = 
        type Model = 
            {
                triggerB : Button

                squareB : Button
                circleB : Button
                triangleB : Button

                resultTB : TextBox

                resetB : Button
            }
        
        let resetModel model = 
            model.triggerB.Content <- "Push Me"
            model.squareB.Content <- "Square"
            model.circleB.Content <- "Circle"
            model.triangleB.Content <- "Triangle"
            model.resultTB.Text <- ""
            model.resetB.Content <- "Start Again"
            model

        let initPanel () = 
            let model =
              {
                triggerB = new Button()
                squareB = new Button()
                circleB = new Button()
                triangleB = new Button()
                resultTB = new TextBox()

                resetB = new Button()
              }
            
            resetModel model

            let sp1 = new StackPanel()
            sp1.Margin <- new Thickness(10.0)
            let sp = new StackPanel()
            sp.Orientation <- Orientation.Horizontal 
            sp.HorizontalAlignment <- HorizontalAlignment.Left
            sp.Children.Add(model.triggerB)
            sp.Children.Add(model.squareB)
            sp.Children.Add(model.circleB)
            sp.Children.Add(model.triangleB)
            sp.Children.Add(model.resultTB)
            sp.Children.Add(model.resetB)

            sp1.Children.Add(sp)

            (sp1, model)


        let makeSwitchPanel () =
            let (panel, model) = initPanel ()
            let colors = ["Red"; "Green"; "Blue"]

            

            let rec engine() =
                resetModel model
                
                let squareSig = sourceEvent  model.squareB.Click 
                let circleSig = sourceEvent  model.circleB.Click 
                let triangleSig = sourceEvent  model.triangleB.Click
                let inputSig =  sourceEvent  model.triggerB.Click 
                                |> loopSig colors
                let resetSig = sourceEvent  model.resetB.Click ==>>  engine 

                let activeSig' = inputSig =>> fun c -> ("Square", c)
                let s = switch activeSig' (run inputSig squareSig circleSig triangleSig)
                let s1 = switch s resetSig 
                s1 

            and run inputSig squareSig circleSig triangleSig =
                let merged = 
                    (squareSig =>> fun _ ->
                        let activeSig' = inputSig =>> fun c -> ("Square", c)
                        switch activeSig' (run inputSig squareSig circleSig triangleSig))
                    .||.
                    (circleSig =>> fun _ ->
                        let activeSig' = inputSig =>> fun c -> ("Circle", c)
                        switch activeSig' (run inputSig squareSig circleSig triangleSig))
                    .||.
                    (triangleSig =>> fun _ ->
                        let activeSig' = inputSig =>> fun c -> ("Triangle", c)
                        switch activeSig' (run inputSig squareSig circleSig triangleSig))
                merged

            engine() =>> fun v -> model.resultTB.Text <- (sprintf "%A" v)
                         
            panel

    module BAllOnTable = 
        type Model = 
            {
                ballPosTB : TextBox
                mousePosTB : TextBox

                resetB : Button
            }
        
        let resetModel model = 
            model.ballPosTB.Text <- ""
            model.mousePosTB.Text <- ""
            model.resetB.Content <- "Start Again"
            model

        let initPanel () = 
            let model =
              {
                ballPosTB = new TextBox()
                mousePosTB = new TextBox()

                resetB = new Button()
              }
            
            resetModel model

            let sp1 = new StackPanel()
            sp1.Margin <- new Thickness(10.0)
            let sp = new StackPanel()
            sp.Orientation <- Orientation.Horizontal 
            sp.HorizontalAlignment <- HorizontalAlignment.Left
            sp.Children.Add(model.ballPosTB)
            sp.Children.Add(model.mousePosTB)
            sp.Children.Add(model.resetB)

            sp1.Children.Add(sp)

            let border = new Border()
            border.BorderThickness <- new Thickness(2.0)
            border.BorderBrush <-  new SolidColorBrush(Colors.Green)

            let canvas = new Canvas ()
            canvas.Width <- 500.0
            canvas.Height <- 500.0
            canvas.Background <- new SolidColorBrush(Colors.LightBlue)
           // border.Child <- canvas

            sp1.Children.Add(canvas)

            (sp1, canvas, model)

        let makeSwitchPanel () =
            let (main, canvas, model) = initPanel ()

            let rec engine() =
                resetModel model
                Event.map (fun v -> 7) canvas.MouseMove
                let mousePosSig = sourceEvent  canvas.MouseMove =>> (fun arg -> arg.GetPosition(canvas).Y)
                let showMousePosSig = mousePosSig =>> (fun y -> model.mousePosTB.Text <- (sprintf "%A" y))
                
                let rec ballAboveTable() = 
                    let s1 = mousePosSig =>> (fun y -> model.ballPosTB.Text <- (sprintf "%A" y))
                    let mouseLowSig = chooseSig (mousePosSig =>> (fun y -> if y >= 100.0 then Some () else None)) 
                    switch s1 (mouseLowSig =>> ballUnderTable)
                and ballUnderTable() = 
                    let onceSig = onceThen (mousePosSig ==>> fun () -> model.ballPosTB.Text <- "Ball on table") none
                    let mouseUpSig = chooseSig (mousePosSig =>> (fun y -> if y < 100.0 then Some () else None)) 
                    switch onceSig (mouseUpSig =>> ballAboveTable)

                let resetSig = sourceEvent model.resetB.Click =>> (fun _ -> dispose showMousePosSig
                                                                            engine() )
                let ballSig = ballAboveTable()
                let s1 = switch ballSig resetSig 
                s1

            engine() 
                         
            main
